﻿using Autofac;
using Common;
using DBContext;
using EV.EventBus;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using ZoneLine.Common;
using ZoneLine.Models;
using ZoneLine.Models.PackageModel;
using ZoneLine.Printers;
using ZoneLine.Stations.HStation;

namespace ZoneLine.Stations
{
    /// <summary>
    /// 后减OP640
    /// </summary>
    /// <remarks>
    /// <para>上支撑螺母拧紧工位</para>
    /// <para> StationCode：OP640    IP：192.168.10.25</para>
    /// </remarks>
    public class HOP040Station : WorkStationDBase
    {
        public HOP040Station()
        {
            _logUiChannel = nameof(HOP040Station) + "uilog";
        }

        //public string CurrentProductType { get; set; }

        public void Init(string ip, int port, string startAddr, string endUploadCodeAddr, string endUploadDataAddr, string allowWorkAddr, string printName)
        {
            Ip = ip;
            Port = port;
            _startAddr = startAddr;
            _readLength = 1028;
            _printerName = printName;
            StationCode = "OP640";
            EndUpLoadCodeAddr = endUploadCodeAddr;
            EndUpLoadDataAddr = endUploadDataAddr;
            AllowWorkAddr = allowWorkAddr;
            StationRecordData = new HOP040StationResult();
            HeartToPlcAddr = "DB1001.0";
            PrintRltAddr = "DB1001.10";
            FormulaAddr = "DB1001.32";

            WorkDirectionAddr = "DB1001.14";
            CurrentProductTypeAddr = "DB1001.2168";
            CurrentProductModelAddr = "DB50.8";
            FormulaNameAddr = "DB50.0";

            //TaskMaster.Default.AddCycleTask(nameof(HOP040Station), 1, () =>
            //{
            //    ////var value = (short)Cache.WorkDirection;
            //    ////WriteData(WorkDirectionAddr, value);
            //    ////_client?.Write(CurrentProductTypeAddr, Cache.CurrentProductType);
            //    //WriteData(CurrentProductTypeAddr, Cache.CurrentProductType);
            //    //WriteData(CurrentProductModelAddr, Cache.WorkDirection == Common.WorkDirectionEnum.Left ? "L" : "R");
            //    //WriteData(FormulaNameAddr, Cache.CurrentProductType);
            //    //var formula = Cache.CurrentFormula.Where(o => o.IP == ip)?.FirstOrDefault().FormulaNumber;
            //    //Console.WriteLine($"ip:{ip},address:{FormulaAddr},val:{formula}");
            //    //_client.Write(FormulaAddr, formula);
            //}, false, EV.EventBus.CycleTask.TimeBaseEnum._1S);

            _logUiChannel = CurrentStationName + "uilog";
            MessageCenter.Subscribe(nameof(HOP040Station), nameof(HOP040Station), (e) =>
            {
                PrintLabel(StationRecordData.AbsScanCode, false);
                return Task.CompletedTask;
            });

            LinkScanBarCodeGun();

            base.InitReSetAddr();
        }

        private string _printerName;

        private short _triggerPrint;

        /// <summary>
        /// 触发打印
        /// </summary>
        public short TriggerPrint
        {
            get { return _triggerPrint; }
            set => SetProperty(ref _triggerPrint, value);
        }

        private int _index;

        /// <summary>
        /// 生产流水号
        /// </summary>
        public int Index
        {
            get { return _index; }
            set => SetProperty(ref _index, value);
        }

        private short _handSignalPrint;

        public short HandSignalPrint
        {
            get { return _handSignalPrint; }
            set { _handSignalPrint = value; }
        }

        #region 2025-07-23 将此工位的测高、打标功能独立出来

        private bool _startUploadCode2;
        /// <summary>
        /// 存储数据开始上传(0初始值无意义，1开始上传) DB1100.DBWO
        /// </summary>
        public bool StartUploadCode2 {
            get { return _startUploadCode2; }
            set => SetProperty(ref _startUploadCode2, value);
        }
        #endregion


        /// <summary>
        /// 打印结论plc地址
        /// </summary>
        public string PrintRltAddr { get; set; }

        public string WorkDirectionAddr { get; set; }

        private HOP040StationResult _stationRecordData;

        public HOP040StationResult StationRecordData
        {
            get { return _stationRecordData; }
            set => SetProperty(ref _stationRecordData, value);
        }

        private void PrintLabel(string barCode, bool needInc = true) {
            //Index = ProductIndexHelper.GetIndex(Cache.Model, 0, Cache.WorkDirection, WorkDirectionEnum.Left, needInc);
            Index = CheckCodeExists(needInc);

            LogWithUi(_logUiChannel, $"在{CurrentStationName}收到打印信息，打印第{Index}号工件", barCode);
            IPrinter printer = null;
            var config = ContainerServer.Container.Resolve<PrintConfigTotal>();
            var templatePath = string.Empty;
            switch (Cache.Model) {
                case ModelEnum.LX:
                    printer = new LXQCPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left) {
                        templatePath = config.LxqcConfig.TemplatePath;
                    } else {
                        templatePath = config.LxqcConfig.TemplatePathR;
                    }
                    break;

                case ModelEnum.SQ:
                    printer = new SQQCPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left) {
                        templatePath = config.Sqqc_Config.TemplatePath;
                    } else {
                        templatePath = config.Sqqc_Config.TemplatePathR;
                    }
                    break;

                case ModelEnum.BQKH:
                    printer = new BQKHPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left) {
                        templatePath = config.BqqcKhConfig.TemplatePath;
                    } else {
                        templatePath = config.BqqcKhConfig.TemplatePathR;
                    }
                    break;

                case ModelEnum.BQLH:
                    printer = new BQLHPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left) {
                        templatePath = config.BqqcLHConfig.TemplatePath;
                    } else {
                        templatePath = config.BqqcLHConfig.TemplatePathR;
                    }
                    break;

                case ModelEnum.WL:
                    printer = new WLQCPrinter();
                    if (Cache.WorkDirection == WorkDirectionEnum.Left) {
                        templatePath = config.WlqcConfig.TemplatePath;
                    } else {
                        templatePath = config.WlqcConfig.TemplatePathR;
                    }
                    break;

                default:
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}收到不存在对应的模板，打印失败", barCode);
                    break;
            }
            if (printer != null) {
                try {
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}开始打印第【{Index}】工件，模板是【${templatePath}】", barCode);
                    var code = printer.PrintLabel(templatePath, _printerName, Index);
                    //打印成功，将数据打印的数据记录到关联表中
                    var printRecord = new AbsPrintResult();
                    printRecord.Brand = Cache.Model.ToString();
                    printRecord.AbsCode = barCode;
                    printRecord.Code = code;
                    printRecord.PrintTime = DateTime.Now;
                    var para = StationEnableConfig.GetPara();
                    printRecord.LeftRight = (int)Cache.WorkDirection;
                    _dal.AddModel(printRecord);
                    _dal.UpdateModel<HOP040StationResult>(p => p.AbsScanCode == printRecord.AbsCode, p => new HOP040StationResult { Code = code });
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}打印第{Index}工件、工件abs码【{barCode}】工件二维码【{code}】完成", barCode);

                    LogWithUi(_logUiChannel, $"在{CurrentStationName}开始发送{PrintRltAddr}点位数据，值为{1}", barCode);
                    var res = WriteData(PrintRltAddr, 1, barCode);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}开始发送{PrintRltAddr}点位数据，值为{1}，res={res}", barCode);
                } catch (Exception ex) {
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}打印失败,失败原因{ex.Message}", barCode);
                    WriteData(PrintRltAddr, 2, barCode);
                }
            }
        }

        protected override void DealData(byte[] content)
        {
            StationRecordData.AbsScanCode = GetPlcString(content, 280);
            StationRecordData.NutScanCode = GetPlcString(content, 322);
            StationRecordData.PartType = GetPlcString(content, 1002);
            StationRecordData.Result = _client.ByteTransform.TransInt16(content, 1000).ToString().Equals("1") ? "OK" : "NG";
            StationRecordData.TigtenTorque = _client.ByteTransform.TransSingle(content, 1016);
            StationRecordData.TigtenAngle = _client.ByteTransform.TransSingle(content, 1020);
            StationRecordData.CycleTime = _client.ByteTransform.TransSingle(content, 1024);
            StationRecordData.ThreadLength = _client.ByteTransform.TransSingle(content, 510);

            TriggerPrint = _client.ByteTransform.TransInt16(content, 500);
            HandSignalPrint = _client.ByteTransform.TransInt16(content, 506);
            //Index = _client.ByteTransform.TransInt16(content, 504);

            //第二个上传条码指令
            StartUploadCode2 = _client.ReadInt16("DB1100.DBW0").Content == (Int16)1;
        }

        protected override void DealWithSignal(string name)
        {
            if (name == nameof(StartUploadCode))
            {
                //todo 上传了条码 这时候验证是否要工作
                if (StartUploadCode)
                {
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}收到上传条码信息命令", StationRecordData.AbsScanCode);

                    LogWithUi(_logUiChannel, $"在{CurrentStationName}工位结论验证,条码信息是{StationRecordData.AbsScanCode}", StationRecordData.AbsScanCode);
                    var validataRlt = Validata(CurrentStationName, StationRecordData.AbsScanCode);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}工位的验证结果是{validataRlt}", StationRecordData.AbsScanCode);
                    var writeRlt = WriteWorkActionToPlc(AllowWorkAddr, validataRlt, StationRecordData.AbsScanCode);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}工位向下位机下发消息，下发{writeRlt}", StationRecordData.AbsScanCode);
                    return;
                }
                else
                {
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}收到上传条码命令变为false", StationRecordData.AbsScanCode);
                    WriteData(EndUpLoadCodeAddr, 0, StationRecordData.AbsScanCode);
                    WriteData(AllowWorkAddr, 0, StationRecordData.AbsScanCode);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}复位工作控制指令和复位上传条码完成指令", StationRecordData.AbsScanCode);

                    //WriteData(PrintRltAddr, 0, StationRecordData.AbsScanCode);//清空PLC打标标记
                    //LogWithUi(_logUiChannel, $"在{CurrentStationName}打标记录,clear", StationRecordData.AbsScanCode);
                    return;
                }
            }

            if (name == nameof(StartUploadData))
            {
                if (StartUploadData)
                {
                    //todo 上传数据 这时候将数据记录到数据库中
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}1收到记录数据命令", StationRecordData.AbsScanCode);
                    var rlt = RecordData();
                    WriteData(EndUpLoadDataAddr, (short)rlt, StationRecordData.AbsScanCode);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}1数据记录,rlt={rlt}", StationRecordData.AbsScanCode);
                    //if (rlt == 1) //liyuxing for update 2025-07-23 将此工位的测高、打标功能独立出来
                    //{
                    //    LogWithUi(_logUiChannel, $"在{CurrentStationName}数据记录完成,打印标签开始", StationRecordData.AbsScanCode);
                    //    PrintLabel();
                    //    LogWithUi(_logUiChannel, $"在{CurrentStationName}数据记录完成,打印标签完成", StationRecordData.AbsScanCode);
                    //}
                } else
                {
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}1收到上传数据信息变为false", StationRecordData.AbsScanCode);
                    WriteData(EndUpLoadDataAddr, 0, StationRecordData.AbsScanCode);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}1数据记录,clear", StationRecordData.AbsScanCode);
                }
            }

            if (name == nameof(TriggerPrint))
            {
                if (TriggerPrint == 1 && HandSignalPrint == 0)
                {
                }
                else
                {
                    // WriteData(PrintRltAddr, 0);
                }
                return;
            }


            #region 2025-07-23 将此工位的测高、打标功能独立出来
            if (name == nameof(StartUploadCode2))
            {
                if (StartUploadCode2)
                {
                    string barCode = _client.ReadString("DB1100.DBX2.0").Content;
                    short result = _client.ReadInt16("DB1100.DBW44").Content;
                    string partType = _client.ReadString("DB1100.DBX46.0").Content;
                    float height = _client.ReadFloat("DB1100.DBD58").Content;

                    LogWithUi(_logUiChannel, $"在{CurrentStationName}2收到上传条码信息命令", barCode);

                    bool rlt = _dal.UpdateModel<HOP040StationResult>(p => p.AbsScanCode == barCode, p => new HOP040StationResult
                    {
                        Result2 = result == 1 ? "OK" : "NG",
                        //PartType = partType,
                        ThreadLength = height
                    });
                    WriteData("DB1101.DBW2", (rlt == true ? (short)1 : (short)2), barCode);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}2工位结论验证,条码信息是{barCode},结果是{rlt},result={result},partType={partType},height={height}", barCode);
                    
                    if (rlt)
                    {
                        LogWithUi(_logUiChannel, $"在{CurrentStationName}2数据记录完成,打印标签开始", barCode);
                        PrintLabel(barCode);
                        LogWithUi(_logUiChannel, $"在{CurrentStationName}2数据记录完成,打印标签完成", barCode);
                    }
                }
                else
                {
                    string barCode = _client.ReadString("DB1100.DBX2.0").Content;
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}2收到上传数据信息变为false", barCode);
                    WriteData("DB1101.DBW2", 0, barCode);
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}2数据记录,clear", barCode);

                    WriteData(PrintRltAddr, 0, barCode);//清空PLC打标标记
                    LogWithUi(_logUiChannel, $"在{CurrentStationName}2打标记录,clear", barCode);
                }
            }
            #endregion

        }

        protected override int RecordData()
        {
            var result = new HOP040StationResult()
            {
                AbsScanCode = StationRecordData.AbsScanCode,
                NutScanCode = StationRecordData.NutScanCode,
                StationCode = this.StationCode,
                PartType = StationRecordData.PartType,
                Result = StationRecordData.Result,
                TigtenTorque = StationRecordData.TigtenTorque,
                TigtenAngle = StationRecordData.TigtenAngle,
                CycleTime = StationRecordData.CycleTime,
                ThreadLength = StationRecordData.ThreadLength,
                Code = StationRecordData.Code,
            };
            var writeRlt = false;
            if (_dal.CheckExist<HOP040StationResult>(p => p.AbsScanCode == result.AbsScanCode))
            {
                var beforeRlt = _dal.GetModel<HOP040StationResult>(p => p.AbsScanCode == result.AbsScanCode);
                result.Id = beforeRlt.Id;
                writeRlt = _dal.UpdateModelSuper<HOP040StationResult>(p => p.AbsScanCode == result.AbsScanCode, result);
            }
            else
            {
                writeRlt = _dal.AddModel(result);
            }
            return writeRlt ? 1 : 2;
        }

        //protected override WorkActionEnum Validata(string stationName, string code, string[] otherStations = null)
        //{
        //    var currentStationName = stationName;
        //    var stationIndex = Cache.WorkStationValidationList.IndexOf(currentStationName);
        //    if (stationIndex == -1)
        //    {
        //        return WorkActionEnum.NoEnable;
        //    }
        //    if (stationIndex > 0)
        //    {
        //        //检测上一个站
        //        var beforeStationName = Cache.WorkStationValidationList[stationIndex - 1];
        //        LogWithUi(_logUiChannel, $"在{currentStationName}工位上一个启动的检查工位是{beforeStationName}");
        //        var checkRlt = CheckCodeExistAndResult(beforeStationName, code);
        //        LogWithUi(_logUiChannel, $"在{beforeStationName}工位检查{code}的结论是{checkRlt}");
        //        if (checkRlt == 1)
        //        {
        //            if (otherStations != null)
        //            {
        //                LogWithUi(_logUiChannel, $"在上个工位{beforeStationName}工位检查{code}的结论是{checkRlt},开始检查校验工位结论");
        //                foreach (var otherStation in otherStations)
        //                {
        //                    LogWithUi(_logUiChannel, $"{currentStationName}检查校验工位{otherStation}是否工作");
        //                    var otherStationResult = CheckCodeExistAndResult(otherStation, code);
        //                    if (otherStationResult == 1)
        //                    {
        //                        LogWithUi(_logUiChannel, $"{currentStationName}检查校验工位{otherStation}工作过，不在本工位进行工作");
        //                        return WorkActionEnum.WorkOkInCheckStation;
        //                    }
        //                }
        //            }
        //            LogWithUi(_logUiChannel, $"在上个工位{beforeStationName}工位检查{code}的结论是{checkRlt},开始检查是否在本工位{currentStationName}结论");
        //            var currentResult = CheckCodeExistAndResult(currentStationName, code);
        //            LogWithUi(_logUiChannel, $"在本工位{currentStationName}工位检查{code}的结论是{currentResult}");
        //            if (currentResult == 1)
        //            {
        //                return WorkActionEnum.HasWorkInCurrent;
        //            }
        //            else
        //            {
        //                return WorkActionEnum.StartWork;
        //            }
        //        }
        //        else if (checkRlt == 2)
        //        {
        //            return WorkActionEnum.WorkNgInBefore;
        //        }
        //        else
        //        {
        //            return WorkActionEnum.NotWorkInBefore;
        //        }
        //    }
        //    else
        //    {
        //        //检查当前工位
        //        if (otherStations != null)
        //        {
        //            LogWithUi(_logUiChannel, $"在{currentStationName}工位不存在上个工位，检查并行工位工作结论");

        //            foreach (var otherStation in otherStations)
        //            {
        //                LogWithUi(_logUiChannel, $"{currentStationName}检查校验工位{otherStation}是否工作");
        //                var otherStationResult = CheckCodeExistAndResult(otherStation, code);
        //                if (otherStationResult == 1)
        //                {
        //                    LogWithUi(_logUiChannel, $"{currentStationName}检查校验工位{otherStation}工作过，不在本工位进行工作");
        //                    return WorkActionEnum.WorkOkInCheckStation;
        //                }
        //            }
        //        }
        //        LogWithUi(_logUiChannel, $"在{currentStationName}工位不存在上个工位，检查在本工位工作结论");
        //        var checkResult = CheckCodeExistAndResult(currentStationName, code);
        //        if (checkResult == 1)
        //        {
        //            return WorkActionEnum.HasWorkInCurrent;
        //        }
        //        else
        //        {
        //            return WorkActionEnum.StartWork;
        //        }
        //    }
        //}



        public int CheckCodeExists(bool needInc)
        {
            var dal = ContainerServer.Container.Resolve<IModelDAL>();
            var index = ProductIndexHelper.GetIndex(Cache.Model, 0, Cache.WorkDirection, WorkDirectionEnum.Left, needInc);
            if (Cache.Model == ModelEnum.LX)
            {
                var code = LXQCPrinter.GetLableBarCode(index);
                var exists = dal.CheckExist<HOP040StationResult>(p => p.Code == code);
                if (exists)
                {
                    Logger.Log.Info($"产品{StationRecordData.AbsScanCode},生成码:{code},已存在");
                    return CheckCodeExists(needInc);
                }
            }
            return index;
        }


        public void LinkScanBarCodeGun() {

            _ = Task.Factory.StartNew(() =>
            {

                try
                {
                    var dal = ContainerServer.Container.Resolve<IModelDAL>();
                    // 配置目标IP和端口号
                    string ipAddress = "192.168.10.118";  // 扫码枪的IP地址
                    int port = 2002;  // 扫码枪的端口号

                    // 创建TcpClient并连接到目标IP和端口
                    TcpClient tcpClient = new TcpClient();
                    tcpClient.Connect(ipAddress, port);

                    // 获取网络流
                    NetworkStream stream = tcpClient.GetStream();

                    // 创建数据缓冲区
                    byte[] buffer = new byte[1024];

                    // 读取数据（例如，扫描的条形码）
                    int bytesRead;
                    while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)
                    {
                        string data = Encoding.ASCII.GetString(buffer, 0, bytesRead);
                        var tempCode = data.Replace(Environment.NewLine, "");
                        LogWithUi(_logUiChannel, $"接收到查重扫码抢数据: {tempCode}");
                        if (!string.IsNullOrEmpty(data))
                        {
                            var res = dal.GetModelList<HOP040StationResult>(p => p.Code == tempCode);
                            WriteData("DB1001.28", res.Count == 1 ? (short)0 : (short)1, StationRecordData.AbsScanCode);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.Log.Error(ex);
                    //throw;
                }
            });
        }

    }
}